package com.bilibili.juc.cf;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.bilibili.juc.cf.base.FutureAdapter;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import static org.junit.Assert.assertTrue;

public class CompletableFutureAllofDemo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException, IOException {
        ExecutorService executor = Executors.newScheduledThreadPool(10);
        CompletableFuture<String> future1
                = CompletableFuture.supplyAsync(() -> {
            System.out.println(" #future1 start...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(" #future1 end...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));

            return "Hello";
        });
        CompletableFuture<String> future2
                = CompletableFuture.supplyAsync(() -> {
            System.out.println(" **future2 start...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(" **future2 end...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
           return  "Beautiful";
        });
        CompletableFuture<String> future3
                = CompletableFuture.supplyAsync(() -> {
            System.out.println(" future3 start...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(" future3 end...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
            return "World";
        });

        System.out.println(" @@main start 1...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));

        List<CompletableFuture<String>> completableFutures = List.of(future1, future2, future3);
        List<ListenableFuture<String>> listenableFutures = completableFutures.stream().map(cf -> FutureAdapter.toListenableFuture(cf, executor)).collect(Collectors.toList());

        ListenableFuture<List<String>> listListenableFuture = Futures.allAsList(listenableFutures);
        System.out.println(" @@main start 2...... " + Thread.currentThread().getName() + " , time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));

// ...

        System.out.println("Futures.allAsList value==>> " + listListenableFuture.get());
        System.out.println(" @@main end 1...... " + Thread.currentThread().getName() + ", time: " + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));

        System.in.read();
        executor.shutdown();
        System.out.println("program end ......");
    }
    /*
 future3 start...... ForkJoinPool.commonPool-worker-3 , time: 2025-02-12 17:55:11
 @@main start 1...... main , time: 2025-02-12 17:55:11
 **future2 start...... ForkJoinPool.commonPool-worker-2 , time: 2025-02-12 17:55:11
 #future1 start...... ForkJoinPool.commonPool-worker-1 , time: 2025-02-12 17:55:11
 @@main start 2...... main , time: 2025-02-12 17:55:11
 future3 end...... ForkJoinPool.commonPool-worker-3 , time: 2025-02-12 17:55:13
 #future1 end...... ForkJoinPool.commonPool-worker-1 , time: 2025-02-12 17:55:13
 **future2 end...... ForkJoinPool.commonPool-worker-2 , time: 2025-02-12 17:55:13
Futures.allAsList value==>> [Hello, Beautiful, World]
 @@main end 1...... main, time: 2025-02-12 17:55:13

program end ......
     */
}
